package com.itcam.maker.meta;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.json.JSONUtil;

/**
 * @author : Cammy.Wu
 * Description : 实现单例模式
 */

/**
 * todo:单例模式的MetaManager类，用于管理Meta对象的实例化
 */
public class MetaManager {

    /**
     * 私有静态变量，用于存储唯一的Meta对象实例
     * 使用volatile关键字确保多线程环境下的可见性
     */
    private static volatile Meta meta;

    /**
     * 私有构造函数，防止外部实例化
     */
    private MetaManager() {
        // 私有构造函数，防止外部实例化
    }

    /**
     * 获取Meta对象的唯一实例
     * 如果实例尚未创建，则通过同步块创建实例
     * @return Meta对象的唯一实例
     */
    public static Meta getMetaObject() {
        // 第一次检查，避免不必要的同步
        if (meta == null) {
            // 同步块，确保只有一个线程可以创建实例
            synchronized (MetaManager.class) {
                // 第二次检查，确保实例尚未被其他线程创建
                if (meta == null) {
                    // 调用initMeta方法初始化Meta对象
                    meta = initMeta();
                }
            }
        }
        // 返回Meta对象的唯一实例
        return meta;
    }

    /**
     * 初始化Meta对象
     *
     * @return 初始化后的Meta对象
     */
    private static Meta initMeta() {
        // 从资源文件中读取meta.json的内容，并以UTF-8编码转换为字符串
        String metaJson = ResourceUtil.readUtf8Str("meta.json");
//        String metaJson = ResourceUtil.readUtf8Str("springboot-init-meta.json");

        // 将JSON字符串转换为Meta对象
        Meta newMeta = JSONUtil.toBean(metaJson, Meta.class);

        // 获取Meta对象中的FileConfig对象
        // Meta.FileConfig fileConfig = newMeta.getFileConfig();

        // 校验和处理默认值
        MetaValidator.doValidAndFill(newMeta);

        // 返回初始化后的Meta对象
        return newMeta;
    }

}

/*
    1.定义了meta属性，用于接受JSON配置。使用volatile关键字修饰，确保多线程环境下的可见性
    2.添加了一个私有构造函数，防止外部用new的方式创建出多个对象，破坏单例
    3.定义了getMetaObject方法，用于获取meta对象，如果是首次获取，则执行initMeta方法来初始化meta对象；否则直接获取已有对象。
        此处使用双重检测锁进行并发控制，即确保了对象获取性能不会被锁影响，也能防止重复实例化。
    4.定义了initMeta方法，用于从JSON文件中获取对象属性并初始化meta对象。当然后续还可以执行对象校验、填充默认值等操作
 */
